import { getToken, setToken } from '@/utils/token'
import { Toast } from 'antd-mobile'
import { ApiRes, Token } from '@/types/data'
import axios, { AxiosError } from 'axios'
import store from '@/store'
import { logout } from '@/store/actions/login'
import history from './history'

const baseURL = 'http://geek.itheima.net/v1_0/'
const http = axios.create({
  baseURL: baseURL,
  timeout: 5000
})

// 添加请求拦截器
http.interceptors.request.use(
  (config) => {
    const token = getToken().token

    if (token) {
      config.headers!.Authorization = `Bearer ${token}`
    }

    return config
  },
  (error) => {
    return Promise.reject(error)
  }
)

// 添加响应拦截器
http.interceptors.response.use(
  (response) => {
    return response
  },
  async (error: AxiosError<ApiRes>) => {
    // 后端没有响应时
    if (!error.response) {
      Toast.show('服务器繁忙，请稍后重试')
      return Promise.reject(error)
    }

    // 1.判断状态是否是401
    if (error.response.status === 401) {
      const token = getToken()

      // 2.判断是否有token和refresh token
      if (token.token && token.refresh_token) {
        try {
          // 2.1 使用默认的axios发送用refresh token 换取新 token 的请求
          const res = await axios.put<ApiRes<Token>>(
            `${baseURL}authorizations`,
            null,
            {
              headers: {
                Authorization: `Bearer ${token.refresh_token}`
              }
            }
          )

          // 2.2换取新 token 成功，将 token 存入本地缓存和 Redux 中
          const newToken: Token = {
            token: res.data.data.token,
            refresh_token: token.refresh_token
          }

          setToken(newToken)

          store.dispatch({
            type: 'login/login',
            payload: newToken
          })

          // 2.3重新发送之前的请求
          // console.log(error.config)
          return http(error.config)
        } catch {
          //  清除token，并跳转到登录页
          store.dispatch(logout())
          history.replace('/login', {
            from: history.location.pathname
          })
        }
      }

      // 3. 没有token或refresh_token的情况
      else {
        // 清除 token，并跳转到登录页
        store.dispatch(logout())
        history.replace('/login', {
          from: history.location.pathname
        })
      }
    }

    // 后端有响应时
    Toast.show(error.response.data.message)
    return Promise.reject(error)
  }
)

export default http
